﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Gamev1
{
    [XmlInclude(typeof(Zombie))]
    [XmlInclude(typeof(Boss))]
    [XmlInclude(typeof(Robot))]
    [XmlInclude(typeof(Alien))]
    public abstract class Enemy : Sprite
    {
        #region Fields

        public double currentHealth, maxHealth;
        private List<Vector2> platformPositionList;
        public string[] animationWalkPath;
        public int power;
        private Rectangle left, right;
        private bool geraaktLinks, geraaktRechts, canHit;
        public int platformWidth;
        public float speed = 0.8f;
        [XmlIgnore]
        public float elapsedTimeAttack, elapsedTimeMovement;
        public float hitDelay = 500f;
        [XmlIgnore]
        public int direction;
        public Vector2 platformPosition;
        [XmlIgnore]
        public Animation animationWalk;
        [XmlIgnore]
        public HealthBar healthBar;
        [XmlIgnore]
        public Texture2D TextureFieldOfView;
        [XmlIgnore]
        public bool canSeeCharacter;
        public bool canDropKey;
        private const float movementDelay = 3500f;

        #endregion

        public Enemy()
        {
            currentHealth = maxHealth = 100;
            platformPositionList = new List<Vector2>();
        }

        public override void draw(SpriteBatch spriteBatch)
        {
            animationWalk.Draw(spriteBatch, this);
            healthBar.Draw(spriteBatch);
        }

        public override void update(GameTime gameTime)
        {
            checkCanHit(gameTime);
            Position += Velocity;
            checkAlive();
            animationWalk.Update(gameTime, direction);
            healthBar.Update(gameTime, this);
            AI(gameTime);
        }

        public virtual void selectRandomPlatform(int randomNumber)
        {
            platformPosition = new Vector2(platformPositionList[randomNumber].X, platformPositionList[randomNumber].Y - Texture.Height);
            this.Position = platformPosition;
        }


        public Rectangle FieldOfView
        {
            get
            {
                int width = 200;
                int height = 78;
                if (direction == (int)Direction.Right)
                {
                    return new Rectangle(
                        (int)Position.X + Rectangle.Width,
                        (int)Position.Y,
                        width,
                        height);
                }
                else
                {
                    return new Rectangle(
                        (int)Position.X - 200,
                        (int)Position.Y,
                        width,
                        height);
                }
            }
        }

        public override void collisionWith(Sprite sprite)
        {
            left = new Rectangle((int)Position.X - 10, (int)Position.Y + 5, 10, Rectangle.Height - 10);
            right = new Rectangle((int)Position.X + Rectangle.Width, (int)Position.Y + 5, 10, Rectangle.Height - 10);

            if (sprite is Character)
            {
                Character character = (Character)sprite;
                if (canHit)
                {
                    hit(character);
                    elapsedTimeAttack = 0f;
                }

                if (right.Intersects(character.Rectangle))
                {
                    if (character.Position.X < Position.X + Rectangle.Width)
                    {
                        character.Position = new Vector2(Position.X + Rectangle.Width, character.Position.Y);
                    }
                }
                else if (left.Intersects(character.Rectangle))
                {
                    if (character.Position.X + character.Rectangle.Width > Position.X)
                    {
                        character.Position = new Vector2(Position.X - character.Rectangle.Width, character.Position.Y);
                    }
                }
            }
        }

        #region Methods
        public virtual void AI(GameTime gameTime)
        {
        }

        public void moveRandomly(GameTime gameTime, int random)
        {
            elapsedTimeMovement += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
            if (elapsedTimeMovement >= movementDelay)
            {
                if (random >= 5)
                {
                    if (atRightEdge())
                    {
                        moveLeft();
                    }
                    else
                    {
                        moveRight();
                    }
                }
                else
                {
                    if (atLeftEdge())
                    {
                        moveRight();
                    }
                    else
                    {
                        moveLeft();
                    }

                }
                elapsedTimeMovement = 0f;
            }
        }

        public void chase(float chaseSpeed)
        {
            if (direction == (int)Direction.Left)
            {
                moveLeft(chaseSpeed);
            }
            else if (direction == (int)Direction.Right)
            {
                moveRight(chaseSpeed);
            }
        }

        public virtual Item dropItem(ContentManager content)
        {
            if (canDropKey)
            {
                Item key = new Key();
                //key.Texture = content.Load<Texture2D>("Items/key");
                key.Position = Position;
                return key;
            }
            Item item = new Item();
            //item.Texture = content.Load<Texture2D>("Items/Health");
            item.Position = Position;
            return item;
        }

        public void move()
        {
            if (atRightEdge() || geraaktLinks && atRightEdge())
            {
                moveLeft();
            }
            else if (atLeftEdge() || geraaktRechts && atLeftEdge())
            {
                moveRight();
            }
        }

        public void moveLeft()
        {
            Velocity = new Vector2(-speed, 0);
            geraaktLinks = false;
            direction = (int)Direction.Left;
        }

        public void moveRight()
        {
            Velocity = new Vector2(speed, 0);
            geraaktRechts = false;
            direction = (int)Direction.Right;
        }

        public void moveLeft(float spd)
        {
            Velocity = new Vector2(-spd, 0);
            direction = (int)Direction.Left;
            geraaktLinks = false;
        }

        public void moveRight(float spd)
        {
            Velocity = new Vector2(spd, 0);
            direction = (int)Direction.Right;
            geraaktRechts = false;
        }

        public void hit(Character character)
        {
            character.Health -= power;
        }

        public override void loadContent(ContentManager content)
        {
            float animationDelay = 250f;
            animationWalk = new Animation(animationDelay);
            animationWalk.initializeTextures(content, animationWalkPath);
            Texture = animationWalk.AnimationTextures[0];
            healthBar = new HealthBar(currentHealth);
            healthBar.LoadContent(content);

        }

        public void checkAlive()
        {
            if (currentHealth <= 0)
            {
                canBeRemoved = true;
            }
        }

        public bool atRightEdge()
        {
            return Position.X >= platformPosition.X + platformWidth - Texture.Width;
        }

        public bool atLeftEdge()
        {
            return Position.X <= platformPosition.X;
        }

        public void checkCanHit(GameTime gameTime)
        {
            elapsedTimeAttack += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
            if (elapsedTimeAttack > hitDelay)
            {
                canHit = true;
            }
            else
            {
                canHit = false;
            }
        }

        #endregion

        #region Getters & setters

        public double calculateHealth(double healthPercentage)
        {
            return (healthPercentage * MaxHealth) / 100;
        }

        [XmlIgnore]
        public double MaxHealth
        {
            get { return maxHealth; }
            set { maxHealth = value; }
        }

        [XmlIgnore]
        public Vector2 Velocity { get; set; }

        [XmlIgnore]
        public bool CanHit
        {
            get { return canHit; }
            set { canHit = value; }
        }

        public List<Vector2> PlatformPositionList
        {
            get { return platformPositionList; }
            set { platformPositionList = value; }
        }

        #endregion
    }
}
